package com.zatech.cgnci.project.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.zatech.cgnci.project.base.context.UserContext;
import com.zatech.cgnci.project.base.enums.*;
import com.zatech.cgnci.project.base.exception.GlobalException;
import com.zatech.cgnci.project.base.utils.*;
import com.zatech.cgnci.project.dto.*;
import com.zatech.cgnci.project.entity.*;
import com.zatech.cgnci.project.mapper.CgnciApprovalInfoMapper;
import com.zatech.cgnci.project.mapper.CgnciApprovalRecordMapper;
import com.zatech.cgnci.project.mapper.CgnciBusinessProjectMapper;
import com.zatech.cgnci.project.service.*;
import com.zatech.cgnci.project.vo.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.util.*;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.stream.Collectors;

/**
 * <p>
 * 业务主表 服务实现类
 * </p>
 *
 * @author Generator
 * @since 2024-12-17
 */
@Service
public class CgnciBusinessProjectServiceImpl extends ServiceImpl<CgnciBusinessProjectMapper, CgnciBusinessProjectDO> implements CgnciBusinessProjectService {

    @Resource
    private CgnciCodeTypeService cgnciCodeTypeService;
    @Resource
    private CgnciDirectInsuranceService cgnciDirectInsuranceService;
    @Resource
    private CgnciDirectInsuranceRiskService cgnciDirectInsuranceRiskService;
    @Resource
    private CgnciDirectInsuranceDetailService cgnciDirectInsuranceDetailService;
    @Resource
    private CgnciReinsuranceInfoService cgnciReinsuranceInfoService;
    @Resource
    private CgnciReinsuranceRiskService cgnciReinsuranceRiskService;
    @Resource
    private CgnciReinsuranceRiskInsuredService cgnciReinsuranceRiskInsuredService;
    @Resource
    private CgnciReinsuranceRiskLayerService cgnciReinsuranceRiskLayerService;
    @Resource
    private CgnciUnderwritingPolicyService cgnciUnderwritingPolicyService;
    @Resource
    private CgnciAccessoryService cgnciAccessoryService;
    @Resource
    private CgnciOperationLogsService cgnciOperationLogsService;
    @Resource
    private CgnciApprovalRecordService approvalRecordService;
    @Resource
    IApprovalService approvalService;
    @Resource
    CgnciApprovalInfoMapper approvalInfoMapper;
    @Resource
    CgnciApprovalRecordMapper approvalRecordMapper;
    @Resource
    CgnciAccessoryService accessoryService;
    @Resource
    CgnciBusinessInsuranceService businessInsuranceService;
    @Resource
    CgnciRateService cgnciRateService;

    @Override
    public IPage<CgnciBusinessProjectPageVO> pageBusinessProject(CgnciBusinessProjectQueryDTO queryDTO) {
        return this.baseMapper.pageBusinessProject(queryDTO.toPage(), queryDTO);
    }

    @Override
    public CgnciBusinessProjectMainVO detail(Long projectId) {
        CgnciBusinessProjectMainVO businessMainVO = new CgnciBusinessProjectMainVO();

        // 基本信息
        CgnciBusinessProjectDO businessMainDO = this.baseMapper.selectById(projectId);
        if (VerifyUtils.isEmpty(businessMainDO)) {
            throw new GlobalException(ResponseCodeEnum.HTTP_REQUEST_SERVICE_ERROR);
        }
        CgnciBusinessProjectVO businessProjectVO = ConvertUtils.convert(businessMainDO, CgnciBusinessProjectVO.class);
        businessMainVO.setBusinessProjectVO(businessProjectVO);

        // 任务流程和镜像数据1对1
        CgnciApprovalInfoDO approvalInfoDO = approvalInfoMapper.selectOne(new LambdaQueryWrapper<CgnciApprovalInfoDO>().eq(CgnciApprovalInfoDO::getFormId, businessMainDO.getProjectId()).eq(CgnciApprovalInfoDO::getFormNo, businessMainDO.getFormNo()));
        if (VerifyUtils.isNotEmpty(approvalInfoDO)) {
            businessMainVO.setApprovalInfoId(approvalInfoDO.getApprovalInfoId());
            businessMainVO.setTaskId(approvalInfoDO.getTaskId());
            businessMainVO.setTaskType(approvalInfoDO.getTaskType());
        }

        // 直保信息
        CompletableFuture<Void> directFuture = CompletableFuture.runAsync(() -> {
            businessMainVO.setDirectInsuranceVO(cgnciDirectInsuranceService.getDirectInsuranceByBusinessId(projectId));
        }, ThreadPoolUtils.getThreadPoolExecutor());

        // 分入信息
        CompletableFuture<Void> divideInFuture = CompletableFuture.runAsync(() -> {
            businessMainVO.setDivideInVO(cgnciReinsuranceInfoService.getDivideInReinsuranceByProjectId(projectId));
        }, ThreadPoolUtils.getThreadPoolExecutor());

        // 超净自留处理方式
        CompletableFuture<Void> policyFuture = CompletableFuture.runAsync(() -> {
            businessMainVO.setUnderwritingPolicyVO(cgnciUnderwritingPolicyService.listUnderwritingPolicyByBusinessId(projectId));
        }, ThreadPoolUtils.getThreadPoolExecutor());

        // 合约分出信息
        CompletableFuture<Void> hyDivideOutFuture = CompletableFuture.runAsync(() -> {
            businessMainVO.setHyDivideOutVOList(cgnciReinsuranceInfoService.listHyDivideOutReinsuranceByProjectId(projectId));
        }, ThreadPoolUtils.getThreadPoolExecutor());

        // 临分分出信息
        CompletableFuture<Void> lfDivideOutFuture = CompletableFuture.runAsync(() -> {
            businessMainVO.setLfDivideOutVO(cgnciReinsuranceInfoService.getLfDivideOutReinsuranceByProjectId(projectId));
        }, ThreadPoolUtils.getThreadPoolExecutor());

        // 文件信息
        CompletableFuture<Void> accessoryFuture = CompletableFuture.runAsync(() -> {
            businessMainVO.setAccessoryVOList(cgnciAccessoryService.listAccessoryListByBusinessId(projectId));
        }, ThreadPoolUtils.getThreadPoolExecutor());
        CompletableFuture.allOf(directFuture, divideInFuture, policyFuture, lfDivideOutFuture, hyDivideOutFuture, accessoryFuture).join();
        return businessMainVO;
    }


    @Override
    @Transactional(rollbackFor = Exception.class)
    public CgnciBusinessProjectDO saveOrUpdateBusinessMain(CgnciBusinessProjectSaveOrUpdateDTO updateDTO) {
        // 获取当前登录用户
        UserEntity user = UserContext.getUser();
        // 校验项目id
        CgnciBusinessProjectDO checkProject = this.getById(updateDTO.getBusinessProjectUpdateDTO().getProjectId());
        if (VerifyUtils.isEmpty(checkProject)) {
            throw new GlobalException(ResponseCodeEnum.HTTP_REQUEST_SERVICE_ERROR, "projectId有误");
        }
        // 校验状态
        if (!"0".equals(checkProject.getStatus()) && !"2".equals(checkProject.getStatus()) && !"5".equals(checkProject.getStatus())) {
            throw new GlobalException(ResponseCodeEnum.HTTP_REQUEST_SERVICE_ERROR, "当前状态不能录入");
        }
        // 提交审核校验数据
        if (VerifyUtils.isNotEmpty(updateDTO.getFlowTaskType()) && "submit".equals(updateDTO.getFlowTaskType())) {
            validation(checkProject, updateDTO);
        }

        // 维护业务名称到工作台
        CgnciApprovalInfoDO approvalInfoDO = approvalInfoMapper.selectOne(new LambdaQueryWrapper<CgnciApprovalInfoDO>()
                .eq(CgnciApprovalInfoDO::getFormId, updateDTO.getBusinessProjectUpdateDTO().getProjectId()));
        if (VerifyUtils.isEmpty(approvalInfoDO)) {
            throw new GlobalException(ResponseCodeEnum.HTTP_REQUEST_SERVICE_ERROR, "任务流程不存在");
        }
        approvalInfoDO.setBusinessName(updateDTO.getBusinessProjectUpdateDTO().getProjectName());
        approvalInfoMapper.updateById(approvalInfoDO);

        CgnciBusinessProjectSaveOrUpdateDTO.CgnciBusinessProjectUpdateDTO businessProjectUpdateDTO = updateDTO.getBusinessProjectUpdateDTO();
        CgnciBusinessProjectDO businessProjectDO = ConvertUtils.convert(businessProjectUpdateDTO, CgnciBusinessProjectDO.class);
        businessProjectDO.setUpdateUser(user.getNameAndCode());
        this.saveOrUpdate(businessProjectDO);

        // 直保信息
        CgnciBusinessProjectSaveOrUpdateDTO.CgnciDirectInsuranceProjectUpdateDTO directInsuranceDTO = updateDTO.getDirectInsuranceDTO();
        if (VerifyUtils.isNotEmpty(directInsuranceDTO)) {
            CgnciDirectInsuranceDO directInsuranceDO = ConvertUtils.convert(directInsuranceDTO, CgnciDirectInsuranceDO.class);
            directInsuranceDO.setBusinessId(businessProjectDO.getProjectId());
            directInsuranceDO.setCreateUser(user.getNameAndCode());
            directInsuranceDO.setUpdateUser(user.getNameAndCode());
            cgnciDirectInsuranceService.saveOrUpdate(directInsuranceDO);
            List<CgnciBusinessProjectSaveOrUpdateDTO.CgnciDirectInsuranceRiskProjectUpdateDTO> directRisks = directInsuranceDTO.getDirectRisks();
            if (VerifyUtils.isNotEmpty(directRisks)) {
                directRisks.forEach(risk -> {
                    CgnciDirectInsuranceRiskDO insuranceRiskDO = ConvertUtils.convert(risk, CgnciDirectInsuranceRiskDO.class);
                    insuranceRiskDO.setDirectInsuranceId(directInsuranceDO.getDirectId());
                    insuranceRiskDO.setCreateUser(user.getNameAndCode());
                    insuranceRiskDO.setUpdateUser(user.getNameAndCode());
                    cgnciDirectInsuranceRiskService.saveOrUpdate(insuranceRiskDO);
                    List<CgnciBusinessProjectSaveOrUpdateDTO.CgnciDirectInsuranceDetailProjectUpdateDTO> details = risk.getDetails();
                    if (VerifyUtils.isNotEmpty(details)) {
                        details.forEach(riskDetail -> {
                            CgnciDirectInsuranceDetailDO detail = ConvertUtils.convert(riskDetail, CgnciDirectInsuranceDetailDO.class);
                            detail.setDirectId(insuranceRiskDO.getRiskId());
                            detail.setCreateUser(user.getNameAndCode());
                            detail.setUpdateUser(user.getNameAndCode());
                            cgnciDirectInsuranceDetailService.saveOrUpdate(detail);

                            // 免赔文件
                            List<CgnciBusinessProjectSaveOrUpdateDTO.AccessoryDTO> accessoryDTOList = riskDetail.getAccessoryDTOList();
                            if (VerifyUtils.isNotEmpty(accessoryDTOList)) {
                                List<CgnciAccessoryDO> accessoryList = new ArrayList<>();
                                accessoryDTOList.forEach(accessory -> {
                                    CgnciAccessoryDO accessoryDO = accessoryService.getById(accessory.getAccId());
                                    // 文件绑定业务数据
                                    accessoryDO.setBusinessId(detail.getDetailId());
                                    accessoryList.add(accessoryDO);
                                });
                                accessoryService.saveOrUpdateBatch(accessoryList);
                            }
                        });
                    }
                });
            }
        }

        // 分入信息
        CgnciBusinessProjectSaveOrUpdateDTO.CgnciReinsuranceInfoProjectUpdateDTO divideInDTO = updateDTO.getDivideInDTO();
        if (VerifyUtils.isNotEmpty(divideInDTO)) {
            CgnciReinsuranceInfoDO divideInDO = ConvertUtils.convert(divideInDTO, CgnciReinsuranceInfoDO.class);
            divideInDO.setBusinessId(businessProjectDO.getProjectId());
            divideInDO.setReinsuranceType("1");
            divideInDO.setCreateUser(user.getNameAndCode());
            divideInDO.setUpdateUser(user.getNameAndCode());
            cgnciReinsuranceInfoService.saveOrUpdate(divideInDO);
            List<CgnciBusinessProjectSaveOrUpdateDTO.CgnciReinsuranceRiskProjectUpdateDTO> reinsuranceRisks = divideInDTO.getRisks();
            if (VerifyUtils.isNotEmpty(reinsuranceRisks)) {
                reinsuranceRisks.forEach(risk -> {
                    CgnciReinsuranceRiskDO riskDO = ConvertUtils.convert(risk, CgnciReinsuranceRiskDO.class);
                    riskDO.setReinsuranceId(divideInDO.getReinsuranceId());
                    riskDO.setCreateUser(user.getNameAndCode());
                    riskDO.setUpdateUser(user.getNameAndCode());
                    cgnciReinsuranceRiskService.saveOrUpdate(riskDO);
                    List<CgnciBusinessProjectSaveOrUpdateDTO.CgnciReinsuranceRiskInsuredProjectUpdateDTO> riskInsureds = risk.getRiskInsureds();
                    if (VerifyUtils.isNotEmpty(riskInsureds)) {
                        riskInsureds.forEach(riskInsured -> {
                            CgnciReinsuranceRiskInsuredDO riskInsuredDO = ConvertUtils.convert(riskInsured, CgnciReinsuranceRiskInsuredDO.class);
                            riskInsuredDO.setReinsuranceRiskId(riskDO.getReinsuranceRiskId());
                            riskInsuredDO.setCreateUser(user.getNameAndCode());
                            riskInsuredDO.setUpdateUser(user.getNameAndCode());
                            cgnciReinsuranceRiskInsuredService.saveOrUpdate(riskInsuredDO);

                            List<CgnciBusinessProjectSaveOrUpdateDTO.CgnciReinsuranceRiskLayerProjectUpdateDTO> riskLayers = riskInsured.getRiskLayers();
                            if (VerifyUtils.isNotEmpty(riskLayers)) {
                                riskLayers.forEach(riskLayerDTO -> {
                                    CgnciReinsuranceRiskLayerDO riskLayer = ConvertUtils.convert(riskLayerDTO, CgnciReinsuranceRiskLayerDO.class);
                                    riskLayer.setReinsuranceRiskId(riskInsuredDO.getRiskInsuredId());
                                    riskLayer.setCreateUser(user.getNameAndCode());
                                    riskLayer.setUpdateUser(user.getNameAndCode());
                                    cgnciReinsuranceRiskLayerService.saveOrUpdate(riskLayer);

                                    // 免赔文件
                                    List<CgnciBusinessProjectSaveOrUpdateDTO.AccessoryDTO> accessoryDTOList = riskLayerDTO.getAccessoryDTOList();
                                    if (VerifyUtils.isNotEmpty(accessoryDTOList)) {
                                        List<CgnciAccessoryDO> accessoryList = new ArrayList<>();
                                        accessoryDTOList.forEach(accessory -> {
                                            CgnciAccessoryDO accessoryDO = accessoryService.getById(accessory.getAccId());
                                            // 文件绑定业务数据
                                            accessoryDO.setBusinessId(riskLayer.getLayerId());
                                            accessoryList.add(accessoryDO);
                                        });
                                        accessoryService.saveOrUpdateBatch(accessoryList);
                                    }
                                });
                            }
                        });
                    }
                });
            }
        }

        // 超净自留处理方式
        List<CgnciBusinessProjectSaveOrUpdateDTO.CgnciUnderwritingPolicyProjectUpdateDTO> underwritingPolicyDTO = updateDTO.getUnderwritingPolicyDTO();
        if (VerifyUtils.isNotEmpty(underwritingPolicyDTO)) {
            List<CgnciUnderwritingPolicyDO> underwritingPolicyDOList = ConvertUtils.convert(underwritingPolicyDTO, CgnciUnderwritingPolicyDO.class);
            underwritingPolicyDOList.forEach(policy -> {
                policy.setBusinessId(businessProjectDO.getProjectId());
                policy.setCreateUser(user.getNameAndCode());
                policy.setUpdateUser(user.getNameAndCode());
            });
            cgnciUnderwritingPolicyService.saveOrUpdateBatch(underwritingPolicyDOList);
        }


        // 合约分出信息
        List<CgnciBusinessProjectSaveOrUpdateDTO.CgnciReinsuranceInfoProjectUpdateDTO> hyDivideOutDTOList = updateDTO.getHyDivideOutDTOList();
        if (VerifyUtils.isNotEmpty(hyDivideOutDTOList)) {
            hyDivideOutDTOList.forEach(hyDivideOutDTO -> {
                CgnciReinsuranceInfoDO hyDivideOutDO = ConvertUtils.convert(hyDivideOutDTO, CgnciReinsuranceInfoDO.class);
                hyDivideOutDO.setBusinessId(businessProjectDO.getProjectId());
                hyDivideOutDO.setReinsuranceType("2");
                hyDivideOutDO.setCreateUser(VerifyUtils.isEmpty(hyDivideOutDO.getCreateUser()) ? user.getNameAndCode() : hyDivideOutDO.getCreateUser());
                hyDivideOutDO.setUpdateUser(user.getNameAndCode());
                cgnciReinsuranceInfoService.saveOrUpdate(hyDivideOutDO);

                List<CgnciBusinessProjectSaveOrUpdateDTO.CgnciReinsuranceRiskProjectUpdateDTO> reinsuranceRisks = hyDivideOutDTO.getRisks();
                if (VerifyUtils.isNotEmpty(reinsuranceRisks)) {
                    reinsuranceRisks.forEach(risk -> {
                        // 合约分出险种信息
                        CgnciReinsuranceRiskDO riskDO = ConvertUtils.convert(risk, CgnciReinsuranceRiskDO.class);
                        riskDO.setReinsuranceId(hyDivideOutDO.getReinsuranceId());
                        riskDO.setCreateUser(user.getNameAndCode());
                        riskDO.setUpdateUser(user.getNameAndCode());
                        cgnciReinsuranceRiskService.saveOrUpdate(riskDO);

                        List<CgnciBusinessProjectSaveOrUpdateDTO.CgnciReinsuranceRiskInsuredProjectUpdateDTO> riskInsureds = risk.getRiskInsureds();
                        if (VerifyUtils.isNotEmpty(riskInsureds)) {
                            riskInsureds.forEach(riskInsured -> {
                                CgnciReinsuranceRiskInsuredDO riskInsuredDO = ConvertUtils.convert(riskInsured, CgnciReinsuranceRiskInsuredDO.class);
                                riskInsuredDO.setReinsuranceRiskId(riskDO.getReinsuranceRiskId());
                                riskInsuredDO.setCreateUser(user.getNameAndCode());
                                riskInsuredDO.setUpdateUser(user.getNameAndCode());
                                cgnciReinsuranceRiskInsuredService.saveOrUpdate(riskInsuredDO);

                                List<CgnciBusinessProjectSaveOrUpdateDTO.CgnciReinsuranceRiskLayerProjectUpdateDTO> riskLayers = riskInsured.getRiskLayers();
                                if (VerifyUtils.isNotEmpty(riskLayers)) {
                                    List<CgnciReinsuranceRiskLayerDO> riskLayersDO = ConvertUtils.convert(riskLayers, CgnciReinsuranceRiskLayerDO.class);
                                    riskLayersDO.forEach(riskLayer -> {
                                        riskLayer.setReinsuranceRiskId(riskInsuredDO.getRiskInsuredId());
                                        riskLayer.setCreateUser(user.getNameAndCode());
                                        riskLayer.setUpdateUser(user.getNameAndCode());
                                    });
                                    cgnciReinsuranceRiskLayerService.saveOrUpdateBatch(riskLayersDO);
                                }
                            });
                        }
                    });
                }
            });
        }

        // 临分分出信息
        CgnciBusinessProjectSaveOrUpdateDTO.CgnciReinsuranceInfoProjectUpdateDTO lfDivideOutDTO = updateDTO.getLfDivideOutDTO();
        if (VerifyUtils.isNotEmpty(lfDivideOutDTO)) {
            CgnciReinsuranceInfoDO lfDivideOutDO = ConvertUtils.convert(lfDivideOutDTO, CgnciReinsuranceInfoDO.class);
            lfDivideOutDO.setBusinessId(businessProjectDO.getProjectId());
            lfDivideOutDO.setReinsuranceType("3");
            lfDivideOutDO.setCreateUser(user.getNameAndCode());
            lfDivideOutDO.setUpdateUser(user.getNameAndCode());
            cgnciReinsuranceInfoService.saveOrUpdate(lfDivideOutDO);
            List<CgnciBusinessProjectSaveOrUpdateDTO.CgnciReinsuranceRiskProjectUpdateDTO> reinsuranceRisks = lfDivideOutDTO.getRisks();
            if (VerifyUtils.isNotEmpty(reinsuranceRisks)) {
                reinsuranceRisks.forEach(risk -> {
                    CgnciReinsuranceRiskDO riskDO = ConvertUtils.convert(risk, CgnciReinsuranceRiskDO.class);
                    riskDO.setReinsuranceId(lfDivideOutDO.getReinsuranceId());
                    riskDO.setCreateUser(user.getNameAndCode());
                    riskDO.setUpdateUser(user.getNameAndCode());
                    cgnciReinsuranceRiskService.saveOrUpdate(riskDO);

                    List<CgnciBusinessProjectSaveOrUpdateDTO.CgnciReinsuranceRiskInsuredProjectUpdateDTO> riskInsureds = risk.getRiskInsureds();
                    if (VerifyUtils.isNotEmpty(riskInsureds)) {
                        riskInsureds.forEach(riskInsured -> {
                            CgnciReinsuranceRiskInsuredDO riskInsuredDO = ConvertUtils.convert(riskInsured, CgnciReinsuranceRiskInsuredDO.class);
                            riskInsuredDO.setReinsuranceRiskId(riskDO.getReinsuranceRiskId());
                            riskInsuredDO.setCreateUser(user.getNameAndCode());
                            riskInsuredDO.setUpdateUser(user.getNameAndCode());
                            cgnciReinsuranceRiskInsuredService.saveOrUpdate(riskInsuredDO);

                            List<CgnciBusinessProjectSaveOrUpdateDTO.CgnciReinsuranceRiskLayerProjectUpdateDTO> riskLayers = riskInsured.getRiskLayers();
                            if (VerifyUtils.isNotEmpty(riskLayers)) {
                                List<CgnciReinsuranceRiskLayerDO> riskLayersDO = ConvertUtils.convert(riskLayers, CgnciReinsuranceRiskLayerDO.class);
                                riskLayersDO.forEach(riskLayer -> {
                                    riskLayer.setReinsuranceRiskId(riskInsuredDO.getRiskInsuredId());
                                    riskLayer.setCreateUser(user.getNameAndCode());
                                    riskLayer.setUpdateUser(user.getNameAndCode());
                                });
                                cgnciReinsuranceRiskLayerService.saveOrUpdateBatch(riskLayersDO);
                            }
                        });
                    }

                });
            }
        }

        // 文件信息
        List<CgnciBusinessProjectSaveOrUpdateDTO.AccessoryDTO> accessoryDTOList = updateDTO.getAccessoryDTOList();
        if (VerifyUtils.isNotEmpty(accessoryDTOList)) {
            List<CgnciAccessoryDO> accessoryList = new ArrayList<>();
            accessoryDTOList.forEach(accessory -> {
                CgnciAccessoryDO accessoryDO = accessoryService.getById(accessory.getAccId());
                // 文件绑定业务数据
                accessoryDO.setBusinessId(businessProjectDO.getProjectId());
                accessoryList.add(accessoryDO);
            });
            accessoryService.saveOrUpdateBatch(accessoryList);
        }
        return checkProject;
    }


    @Override
    @Transactional(rollbackFor = Exception.class)
    public void submit(FlowTaskSubmitDTO flowTaskDTO) {
        // 获取当前登录用户
        UserEntity user = UserContext.getUser();
        CgnciBusinessProjectDO businessMainDO = this.getById(flowTaskDTO.getFormId());
        // 校验是否存在
        if (VerifyUtils.isEmpty(businessMainDO)) {
            throw new GlobalException(ResponseCodeEnum.HTTP_REQUEST_SERVICE_ERROR);
        }
        FlowTaskVO submit = approvalService.submit(flowTaskDTO);
        // 回调提交审核状态流程
        businessMainDO.setStatus(submit.getStatus());
        //操作日志
        String remark = businessMainDO.getRemark() == null ? "" : businessMainDO.getRemark();
        //区分场景
        String operationType = "5".equals(businessMainDO.getStatus()) ? OperationTypeEnum.SUBMIT_INVALID_PROJECT.getCode() : OperationTypeEnum.SUBMIT_CREATE_PROJECT.getCode();
        cgnciOperationLogsService.insertOperationLogs(String.valueOf(businessMainDO.getProjectId()), BusinessScenariosEnum.POLICY.getCode(), operationType, remark, user.getNameAndCode());
        /*CgnciOperationLogsDTO operationLogsDTO = new CgnciOperationLogsDTO();
        ApprovalRecordVO approvalRecordVo = approvalRecordService.getPreviousApprovalRecord(businessMainDO.getProjectId());
        String content = String.format("{%s}{%s}{%s} 流转至{%s}", BusinessStatusEnum.getDescByCode(submit.getStatus()), approvalRecordVo.getTaskType(), approvalRecordVo.getTaskId(), approvalRecordVo.getCurrentApproverAndName());
        operationLogsDTO.setBizNo(String.valueOf(businessMainDO.getProjectId()));
        operationLogsDTO.setBizType(BusinessScenariosEnum.POLICY.getCode());
        operationLogsDTO.setContent(content);
        operationLogsDTO.setOperationType(OperationTypeEnum.TASK_TRANSFER.getCode());
        operationLogsDTO.setCreator("系统");
        cgnciOperationLogsService.saveLog(operationLogsDTO);*/

        this.updateById(businessMainDO);

    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void approve(FlowTaskApprovalDTO flowTaskDTO) {
        // 获取当前登录用户
        UserEntity user = UserContext.getUser();
        // 校验是否存在
        CgnciBusinessProjectDO businessMainDO = this.getById(flowTaskDTO.getFormId());
        if (VerifyUtils.isEmpty(businessMainDO)) {
            throw new GlobalException(ResponseCodeEnum.HTTP_REQUEST_SERVICE_ERROR);
        }
        FlowTaskVO approve = approvalService.approve(flowTaskDTO);
        // 回调审批通过状态流程
        businessMainDO.setStatus(approve.getStatus());

        if (1 == approve.getIsEnd()) {
            businessMainDO.setIsMirror("0");
            businessMainDO.setIsEffective("1");

            // 判断项目编号是否有值
            if (VerifyUtils.isEmpty(businessMainDO.getProjectNo())) {
                // 审批通过之后,更新业务编号
                String businessNo = cgnciCodeTypeService.getBusinessNo("xmbh", "number");
                // P+承保年度+0001
                businessMainDO.setProjectNo("P" + businessMainDO.getProjectYear() + businessNo);
            }

            // 审批通过之后,根据工作流配置的模块id(模块id可以有多个分组任务,比如新增任务和编辑任务)查询所有的业务数据,
            // 需要把最新审批通过的业务数据变为不是镜像数据,之前不是镜像数据的业务数据变更为镜像数据
            List<CgnciApprovalInfoDO> cgnciApprovalInfoDOS = approvalInfoMapper.selectList(new LambdaQueryWrapper<CgnciApprovalInfoDO>()
                    .eq(CgnciApprovalInfoDO::getFormNo, approve.getFormNo())
                    .in(CgnciApprovalInfoDO::getStatus, Arrays.asList("3", "7"))
                    .orderByDesc(CgnciApprovalInfoDO::getCreateTime).last("limit 2"));
            if (cgnciApprovalInfoDOS.size() == 2) {
                CgnciApprovalInfoDO firstApprovalInfo = cgnciApprovalInfoDOS.get(0);
                CgnciApprovalInfoDO secondApprovalInfo = cgnciApprovalInfoDOS.get(1);
                // 标记最近一条审批通过的业务数据为非镜像数据
                CgnciBusinessProjectDO firstBusinessProject = this.getById(firstApprovalInfo.getFormId());
                firstBusinessProject.setIsMirror("0");
                firstBusinessProject.setIsEffective("1");
                this.updateById(firstBusinessProject);

                // 标记之后的一个业务数据为镜像数据
                CgnciBusinessProjectDO secondBusinessProject = this.getById(secondApprovalInfo.getFormId());
                secondBusinessProject.setIsMirror("1");
                secondBusinessProject.setIsEffective("0");
                this.updateById(secondBusinessProject);
            }
        }
        this.updateById(businessMainDO);


        //区分作废申请、创建申请
        String operationType = "7".equals(approve.getStatus()) ? OperationTypeEnum.INVALID_PROJECT_PASS.getCode() : OperationTypeEnum.CREATE_PROJECT_PASS.getCode();
        //记录操作日志
        cgnciOperationLogsService.insertOperationLogs(String.valueOf(businessMainDO.getProjectId()), BusinessScenariosEnum.POLICY.getCode(), operationType, flowTaskDTO.getApproverOpinions(), user.getNameAndCode());
        /*CgnciOperationLogsDTO operationLogsDTO = new CgnciOperationLogsDTO();
        ApprovalRecordVO approvalRecordVo = approvalRecordService.getPreviousApprovalRecord(businessMainDO.getProjectId());
        String content = String.format("{%s}{%s}{%s} 流转至{%s}", BusinessStatusEnum.getDescByCode(approve.getStatus()), approvalRecordVo.getTaskType(), approvalRecordVo.getTaskId(), approvalRecordVo.getCurrentApproverAndName());
        operationLogsDTO.setBizNo(String.valueOf(businessMainDO.getProjectId()));
        operationLogsDTO.setBizType(BusinessScenariosEnum.POLICY.getCode());
        operationLogsDTO.setContent(content);
        operationLogsDTO.setOperationType(OperationTypeEnum.TASK_TRANSFER.getCode());
        operationLogsDTO.setCreator("系统");
        cgnciOperationLogsService.saveLog(operationLogsDTO);*/
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void back(FlowTaskBackDTO flowTaskDTO) {
        // 获取当前登录用户
        UserEntity user = UserContext.getUser();
        // 校验年度承保计划是否存在
        CgnciBusinessProjectDO businessMainDO = this.getById(flowTaskDTO.getFormId());
        if (VerifyUtils.isEmpty(businessMainDO)) {
            throw new GlobalException(ResponseCodeEnum.HTTP_REQUEST_SERVICE_ERROR);
        }
        FlowTaskVO back = approvalService.back(flowTaskDTO);
        String operationType = "6".equals(businessMainDO.getStatus()) ? OperationTypeEnum.INVALID_PROJECT_BACK.getCode() : OperationTypeEnum.CREATE_PROJECT_BACK.getCode();

        // 回调审批通过状态流程
        businessMainDO.setStatus(back.getStatus());
        CgnciOperationLogsDTO operationLogsDTO = new CgnciOperationLogsDTO();
        operationLogsDTO.setBizNo(String.valueOf(businessMainDO.getProjectId()));
        operationLogsDTO.setBizType(BusinessScenariosEnum.POLICY.getCode());
        operationLogsDTO.setOperationType(operationType);
        operationLogsDTO.setContent(flowTaskDTO.getApproverOpinions());
        operationLogsDTO.setCreator(user.getNameAndCode());
        cgnciOperationLogsService.saveLog(operationLogsDTO);
        this.updateById(businessMainDO);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void signOut(Long projectId) {
        // 获取当前登录用户
        UserEntity user = UserContext.getUser();
        CgnciBusinessProjectDO businessMainDO = this.baseMapper.selectById(projectId);
        if (VerifyUtils.isEmpty(businessMainDO)) {
            throw new GlobalException(ResponseCodeEnum.PARAMS_ILLEGAL, "inPlanId有误");
        }
        // 判断当前状态是否为 录入中
        if (!"0".equals(businessMainDO.getStatus()) && !"2".equals(businessMainDO.getStatus())) {
            throw new GlobalException(ResponseCodeEnum.HTTP_REQUEST_SERVICE_ERROR, "当前状态不能注销");
        }
        approvalService.cancelTask(FlowTaskCancelDTO.builder().formId(String.valueOf(businessMainDO.getProjectId())).formNo(businessMainDO.getFormNo()).build());
        //记录操作日志,区分注销场景
        String operationType = "5".equals(businessMainDO.getStatus()) ? OperationTypeEnum.CANCEL_INVALID_PROJECT.getCode() : OperationTypeEnum.CANCEL_CREATE_PROJECT.getCode();
        cgnciOperationLogsService.insertOperationLogs(String.valueOf(businessMainDO.getProjectId()), BusinessScenariosEnum.POLICY.getCode(), operationType, "", user.getNameAndCode());
        // 回调提交审核状态流程
        businessMainDO.setStatus("4");
        this.updateById(businessMainDO);

    }

    @Override
    public List<ApprovalRecordVO> log(Long projectId) {
        List<CgnciApprovalRecordDO> approvalRecordDOList = approvalRecordMapper.selectList(new LambdaQueryWrapper<CgnciApprovalRecordDO>().eq(CgnciApprovalRecordDO::getFormId, projectId));
        return ConvertUtils.convert(approvalRecordDOList, ApprovalRecordVO.class);
    }

    @Override
    public CgnciBusinessProjectDO nextCopy(CgnciBusinessProjectNextCopyDTO nextCopyDTO) {
        // 获取当前登录用户
        UserEntity user = UserContext.getUser();
        // 校验复制的项目id
        CgnciBusinessProjectDO copyProject = this.getById(nextCopyDTO.getOriginalProjectId());
        if (VerifyUtils.isEmpty(copyProject)) {
            throw new GlobalException(ResponseCodeEnum.HTTP_REQUEST_SERVICE_ERROR, "请输入正确的项目编号");
        }
        if (!"1".equals(copyProject.getIsEffective()) && !"3".equals(copyProject.getStatus())) {
            throw new GlobalException(ResponseCodeEnum.HTTP_REQUEST_SERVICE_ERROR, "该项目不是已生效的状态，不允许复制");
        }

        CgnciBusinessProjectMainVO projectVO = this.detail(nextCopyDTO.getOriginalProjectId());
        // 基本信息
        // 险种、保单币种、汇率约定方式、汇率、业务承接类型复制外，其他均不复制
        CgnciBusinessProjectDO businessProject = CgnciBusinessProjectDO.builder()
                .formNo(BeanUtils.getUUID()).projectType("2").originalProjectId(nextCopyDTO.getOriginalProjectId())
                .riskClass(copyProject.getRiskClass()).riskClassCode(copyProject.getRiskClassCode()).riskSubType(copyProject.getRiskSubType()).riskSubTypeCode(copyProject.getRiskSubTypeCode())
                .currency(copyProject.getCurrency()).exchangeRate(copyProject.getExchangeRate()).exchangeRateType(copyProject.getExchangeRateType())
                .projectAcceptanceType(copyProject.getProjectAcceptanceType())
                .pml(copyProject.getPml()).isSurveyReport(copyProject.getIsSurveyReport())
                .createUser(user.getNameAndCode()).updateUser(user.getNameAndCode()).build();
        this.save(businessProject);

        // 直保信息
        CgnciDirectInsuranceVO directInsuranceVO = projectVO.getDirectInsuranceVO();
        if (VerifyUtils.isNotEmpty(directInsuranceVO)) {
            CgnciDirectInsuranceDO directInsuranceDO = ConvertUtils.convert(directInsuranceVO, CgnciDirectInsuranceDO.class);
            directInsuranceDO.setDirectId(null);
            directInsuranceDO.setBusinessId(businessProject.getProjectId());
            directInsuranceDO.setCreateUser(user.getNameAndCode());
            directInsuranceDO.setUpdateUser(user.getNameAndCode());
            cgnciDirectInsuranceService.save(directInsuranceDO);

            List<CgnciDirectInsuranceRiskVO> insuranceRisks = directInsuranceVO.getInsuranceRisks();
            if (VerifyUtils.isNotEmpty(insuranceRisks)) {
                insuranceRisks.forEach(risk -> {
                    CgnciDirectInsuranceRiskDO insuranceRisksDO = ConvertUtils.convert(risk, CgnciDirectInsuranceRiskDO.class);
                    insuranceRisksDO.setRiskId(null);
                    insuranceRisksDO.setDirectInsuranceId(directInsuranceDO.getDirectId());
                    insuranceRisksDO.setCreateUser(user.getNameAndCode());
                    insuranceRisksDO.setUpdateUser(user.getNameAndCode());
                    cgnciDirectInsuranceRiskService.save(insuranceRisksDO);

                    List<CgnciDirectInsuranceDetailVO> detailVOS = risk.getDetails();
                    if (VerifyUtils.isNotEmpty(detailVOS)) {
                        List<CgnciDirectInsuranceDetailDO> detailsDOS = ConvertUtils.convert(detailVOS, CgnciDirectInsuranceDetailDO.class);
                        detailsDOS.forEach(detail -> {
                            detail.setDetailId(null);
                            detail.setDirectId(insuranceRisksDO.getRiskId());
                            detail.setCreateUser(user.getNameAndCode());
                            detail.setUpdateUser(user.getNameAndCode());
                        });
                        cgnciDirectInsuranceDetailService.saveBatch(detailsDOS);
                    }
                });
            }
        }

        // 分入信息
        CgnciReinsuranceInfoProjectVO divideInVO = projectVO.getDivideInVO();
        if (VerifyUtils.isNotEmpty(divideInVO)) {
            CgnciReinsuranceInfoDO divideInDO = ConvertUtils.convert(divideInVO, CgnciReinsuranceInfoDO.class);
            divideInDO.setReinsuranceId(null);
            divideInDO.setBusinessId(businessProject.getProjectId());
            divideInDO.setCreateUser(user.getNameAndCode());
            divideInDO.setUpdateUser(user.getNameAndCode());
            cgnciReinsuranceInfoService.save(divideInDO);

            List<CgnciReinsuranceRiskProjectVO> divideInRiskVOList = divideInVO.getRisks();
            if (VerifyUtils.isNotEmpty(divideInRiskVOList)) {
                divideInRiskVOList.forEach(risk -> {
                    CgnciReinsuranceRiskDO riskDO = ConvertUtils.convert(risk, CgnciReinsuranceRiskDO.class);
                    riskDO.setReinsuranceRiskId(null);
                    riskDO.setReinsuranceId(divideInDO.getReinsuranceId());
                    riskDO.setCreateUser(user.getNameAndCode());
                    riskDO.setUpdateUser(user.getNameAndCode());
                    cgnciReinsuranceRiskService.save(riskDO);

                    List<CgnciReinsuranceRiskInsuredProjectVO> riskInsureds = risk.getRiskInsureds();
                    if (VerifyUtils.isNotEmpty(riskInsureds)) {
                        riskInsureds.forEach(riskInsured -> {
                            CgnciReinsuranceRiskInsuredDO riskInsuredDO = ConvertUtils.convert(riskInsured, CgnciReinsuranceRiskInsuredDO.class);
                            riskInsuredDO.setRiskInsuredId(null);
                            riskInsuredDO.setReinsuranceRiskId(riskDO.getReinsuranceRiskId());
                            riskInsuredDO.setCreateUser(user.getNameAndCode());
                            riskInsuredDO.setUpdateUser(user.getNameAndCode());
                            cgnciReinsuranceRiskInsuredService.save(riskInsuredDO);

                            List<CgnciReinsuranceRiskLayerProjectVO> riskLayersVO = riskInsured.getRiskLayers();
                            if (VerifyUtils.isNotEmpty(riskLayersVO)) {
                                List<CgnciReinsuranceRiskLayerDO> riskLayersDO = ConvertUtils.convert(riskLayersVO, CgnciReinsuranceRiskLayerDO.class);
                                riskLayersDO.forEach(riskLayer -> {
                                    riskLayer.setLayerId(null);
                                    riskLayer.setReinsuranceRiskId(riskInsuredDO.getRiskInsuredId());
                                    riskLayer.setCreateUser(user.getNameAndCode());
                                    riskLayer.setUpdateUser(user.getNameAndCode());
                                });
                                cgnciReinsuranceRiskLayerService.saveBatch(riskLayersDO);
                            }
                        });
                    }
                });
            }
        }

        // 超净自留处理方式
        List<CgnciUnderwritingPolicyVO> underwritingPolicyVOList = projectVO.getUnderwritingPolicyVO();
        List<CgnciUnderwritingPolicyDO> underwritingPolicyDOList = ConvertUtils.convert(underwritingPolicyVOList, CgnciUnderwritingPolicyDO.class);
        underwritingPolicyDOList.forEach(policy -> {
            policy.setPolicyId(null);
            policy.setBusinessId(businessProject.getProjectId());
            policy.setCreateUser(user.getNameAndCode());
            policy.setUpdateUser(user.getNameAndCode());
        });
        cgnciUnderwritingPolicyService.saveBatch(underwritingPolicyDOList);

        // 合约分出信息
        List<CgnciReinsuranceInfoProjectVO> hyDivideOutVOList = projectVO.getHyDivideOutVOList();
        if (VerifyUtils.isNotEmpty(hyDivideOutVOList)) {
            hyDivideOutVOList.forEach(hyDivideOutVO -> {
                CgnciReinsuranceInfoDO hyDivideOutDO = ConvertUtils.convert(hyDivideOutVO, CgnciReinsuranceInfoDO.class);
                hyDivideOutDO.setReinsuranceId(null);
                hyDivideOutDO.setBusinessId(businessProject.getProjectId());
                hyDivideOutDO.setCreateUser(user.getNameAndCode());
                hyDivideOutDO.setUpdateUser(user.getNameAndCode());
                cgnciReinsuranceInfoService.save(hyDivideOutDO);

                List<CgnciReinsuranceRiskProjectVO> hyDivideOutRiskVOList = hyDivideOutVO.getRisks();
                if (VerifyUtils.isNotEmpty(hyDivideOutRiskVOList)) {
                    hyDivideOutRiskVOList.forEach(risk -> {
                        CgnciReinsuranceRiskDO riskDO = ConvertUtils.convert(risk, CgnciReinsuranceRiskDO.class);
                        riskDO.setReinsuranceRiskId(null);
                        riskDO.setReinsuranceId(hyDivideOutDO.getReinsuranceId());
                        riskDO.setCreateUser(user.getNameAndCode());
                        riskDO.setUpdateUser(user.getNameAndCode());
                        cgnciReinsuranceRiskService.save(riskDO);

                        List<CgnciReinsuranceRiskInsuredProjectVO> riskInsureds = risk.getRiskInsureds();
                        if (VerifyUtils.isNotEmpty(riskInsureds)) {
                            riskInsureds.forEach(riskInsured -> {
                                CgnciReinsuranceRiskInsuredDO riskInsuredDO = ConvertUtils.convert(riskInsured, CgnciReinsuranceRiskInsuredDO.class);
                                riskInsuredDO.setRiskInsuredId(null);
                                riskInsuredDO.setReinsuranceRiskId(riskDO.getReinsuranceRiskId());
                                riskInsuredDO.setCreateUser(user.getNameAndCode());
                                riskInsuredDO.setUpdateUser(user.getNameAndCode());
                                cgnciReinsuranceRiskInsuredService.save(riskInsuredDO);

                                List<CgnciReinsuranceRiskLayerProjectVO> riskLayersVO = riskInsured.getRiskLayers();
                                if (VerifyUtils.isNotEmpty(riskLayersVO)) {
                                    List<CgnciReinsuranceRiskLayerDO> riskLayersDO = ConvertUtils.convert(riskLayersVO, CgnciReinsuranceRiskLayerDO.class);
                                    riskLayersDO.forEach(riskLayer -> {
                                        riskLayer.setLayerId(null);
                                        riskLayer.setReinsuranceRiskId(riskInsuredDO.getRiskInsuredId());
                                        riskLayer.setCreateUser(user.getNameAndCode());
                                        riskLayer.setUpdateUser(user.getNameAndCode());
                                    });
                                    cgnciReinsuranceRiskLayerService.saveBatch(riskLayersDO);
                                }
                            });
                        }
                    });
                }
            });
        }

        // 临分分出信息
        CgnciReinsuranceInfoProjectVO lfDivideOutVO = projectVO.getLfDivideOutVO();
        if (VerifyUtils.isNotEmpty(lfDivideOutVO)) {
            CgnciReinsuranceInfoDO lfDivideOuDO = ConvertUtils.convert(lfDivideOutVO, CgnciReinsuranceInfoDO.class);
            lfDivideOuDO.setReinsuranceId(null);
            lfDivideOuDO.setBusinessId(businessProject.getProjectId());
            lfDivideOuDO.setCreateUser(user.getNameAndCode());
            lfDivideOuDO.setUpdateUser(user.getNameAndCode());
            cgnciReinsuranceInfoService.save(lfDivideOuDO);

            List<CgnciReinsuranceRiskProjectVO> lfDivideOutRiskVOList = lfDivideOutVO.getRisks();
            if (VerifyUtils.isNotEmpty(lfDivideOutRiskVOList)) {
                lfDivideOutRiskVOList.forEach(risk -> {
                    CgnciReinsuranceRiskDO riskDO = ConvertUtils.convert(risk, CgnciReinsuranceRiskDO.class);
                    riskDO.setReinsuranceRiskId(null);
                    riskDO.setReinsuranceId(lfDivideOuDO.getReinsuranceId());
                    riskDO.setCreateUser(user.getNameAndCode());
                    riskDO.setUpdateUser(user.getNameAndCode());
                    cgnciReinsuranceRiskService.save(riskDO);

                    List<CgnciReinsuranceRiskInsuredProjectVO> riskInsureds = risk.getRiskInsureds();
                    if (VerifyUtils.isNotEmpty(riskInsureds)) {
                        riskInsureds.forEach(riskInsured -> {
                            CgnciReinsuranceRiskInsuredDO riskInsuredDO = ConvertUtils.convert(riskInsured, CgnciReinsuranceRiskInsuredDO.class);
                            riskInsuredDO.setRiskInsuredId(null);
                            riskInsuredDO.setReinsuranceRiskId(riskDO.getReinsuranceRiskId());
                            riskInsuredDO.setCreateUser(user.getNameAndCode());
                            riskInsuredDO.setUpdateUser(user.getNameAndCode());
                            cgnciReinsuranceRiskInsuredService.save(riskInsuredDO);

                            List<CgnciReinsuranceRiskLayerProjectVO> riskLayersVO = riskInsured.getRiskLayers();
                            if (VerifyUtils.isNotEmpty(riskLayersVO)) {
                                List<CgnciReinsuranceRiskLayerDO> riskLayersDO = ConvertUtils.convert(riskLayersVO, CgnciReinsuranceRiskLayerDO.class);
                                riskLayersDO.forEach(riskLayer -> {
                                    riskLayer.setLayerId(null);
                                    riskLayer.setReinsuranceRiskId(riskInsuredDO.getRiskInsuredId());
                                    riskLayer.setCreateUser(user.getNameAndCode());
                                    riskLayer.setUpdateUser(user.getNameAndCode());
                                });
                                cgnciReinsuranceRiskLayerService.saveBatch(riskLayersDO);
                            }
                        });
                    }
                });
            }
        }

        // 文件信息
        List<CgnciAccessoryVO> accessoryVOList = projectVO.getAccessoryVOList();
        if (VerifyUtils.isNotEmpty(accessoryVOList)) {
            List<CgnciAccessoryDO> accessoryList = new ArrayList<>();
            accessoryVOList.forEach(accessory -> {
                CgnciAccessoryDO accessoryDO = accessoryService.getById(accessory.getAccId());
                // 设置插入数据
                accessoryDO.setAccId(null);
                accessoryDO.setBusinessId(businessProject.getProjectId());
                accessoryDO.setCreateUser(user.getNameAndCode());
                accessoryDO.setUpdateUser(user.getNameAndCode());
                accessoryList.add(accessoryDO);
            });
            accessoryService.saveBatch(accessoryList);
        }
        return businessProject;
    }

    @Override
    public CgnciBusinessProjectDO cancel(Long projectId) {
        // 获取当前登录用户
        UserEntity user = UserContext.getUser();
        // 校验复制的项目id
        CgnciBusinessProjectDO checkBusinessProject = this.getById(projectId);
        if (VerifyUtils.isEmpty(checkBusinessProject)) {
            throw new GlobalException(ResponseCodeEnum.HTTP_REQUEST_SERVICE_ERROR, "projectId有误");
        }

        // 只有已完成才能作废
        if (!"3".equals(checkBusinessProject.getStatus())) {
            throw new GlobalException(ResponseCodeEnum.HTTP_REQUEST_SERVICE_ERROR, "当前状态不能作废");
        }

        // 校验该项目已作废
        // 校验同一个分组,同一个业务编号是否结束,否则抛出异常
        CgnciApprovalInfoDO approvalInfoDO = approvalInfoMapper.selectOne(new LambdaQueryWrapper<CgnciApprovalInfoDO>()
                .eq(CgnciApprovalInfoDO::getFormNo, checkBusinessProject.getFormNo())
                .eq(CgnciApprovalInfoDO::getApprovalConfigGroupId, "006")
                .eq(CgnciApprovalInfoDO::getStatus, "7"));
        if (VerifyUtils.isNotEmpty(approvalInfoDO)) {
            throw new GlobalException(ResponseCodeEnum.HTTP_REQUEST_SERVICE_ERROR, "该项目已经作废,不能再次作废");
        }

        // 关联保单的项目不能作废
        List<CgnciBusinessInsuranceDO> insuranceList = businessInsuranceService.list(new LambdaQueryWrapper<CgnciBusinessInsuranceDO>()
                .notIn(CgnciBusinessInsuranceDO::getStatus, "4")
                .eq(CgnciBusinessInsuranceDO::getBusinessType, "1")
                .eq(CgnciBusinessInsuranceDO::getProjectId, projectId));
        if (VerifyUtils.isNotEmpty(insuranceList)) {
            throw new GlobalException(ResponseCodeEnum.HTTP_REQUEST_SERVICE_ERROR, "该项目已经关联保单,不能作废");
        }

        CgnciBusinessProjectMainVO projectVO = this.detail(projectId);
        // 基本信息
        CgnciBusinessProjectVO businessProjectVO = projectVO.getBusinessProjectVO();
        CgnciBusinessProjectDO businessProject = ConvertUtils.convert(businessProjectVO, CgnciBusinessProjectDO.class);
        // 设置插入数据
        businessProject.setProjectId(null);
        // 使用之前的流程编号绑定业务数据,目的是用来关联工作流,校验同一流程只能有一个在途的任务
        businessProject.setFormNo(checkBusinessProject.getFormNo());
        // 设置该数据为镜像数据
        businessProject.setIsMirror("1");
        businessProject.setStatus("0");
        businessProject.setIsEffective("0");
        businessProject.setCreateUser(user.getNameAndCode());
        businessProject.setCreateTime(new Date());
        businessProject.setUpdateUser(user.getNameAndCode());
        businessProject.setUpdateTime(new Date());
        this.save(businessProject);

        // 直保信息
        CgnciDirectInsuranceVO directInsuranceVO = projectVO.getDirectInsuranceVO();
        if (VerifyUtils.isNotEmpty(directInsuranceVO)) {
            CgnciDirectInsuranceDO directInsuranceDO = ConvertUtils.convert(directInsuranceVO, CgnciDirectInsuranceDO.class);
            directInsuranceDO.setDirectId(null);
            directInsuranceDO.setBusinessId(businessProject.getProjectId());
            directInsuranceDO.setCreateUser(user.getNameAndCode());
            directInsuranceDO.setUpdateUser(user.getNameAndCode());
            cgnciDirectInsuranceService.save(directInsuranceDO);

            List<CgnciDirectInsuranceRiskVO> insuranceRisks = directInsuranceVO.getInsuranceRisks();
            if (VerifyUtils.isNotEmpty(insuranceRisks)) {
                insuranceRisks.forEach(risk -> {
                    CgnciDirectInsuranceRiskDO insuranceRisksDO = ConvertUtils.convert(risk, CgnciDirectInsuranceRiskDO.class);
                    insuranceRisksDO.setRiskId(null);
                    insuranceRisksDO.setDirectInsuranceId(directInsuranceDO.getDirectId());
                    insuranceRisksDO.setCreateUser(user.getNameAndCode());
                    insuranceRisksDO.setUpdateUser(user.getNameAndCode());
                    cgnciDirectInsuranceRiskService.save(insuranceRisksDO);

                    List<CgnciDirectInsuranceDetailVO> detailVOS = risk.getDetails();
                    if (VerifyUtils.isNotEmpty(detailVOS)) {
                        List<CgnciDirectInsuranceDetailDO> detailsDOS = ConvertUtils.convert(detailVOS, CgnciDirectInsuranceDetailDO.class);
                        detailsDOS.forEach(detail -> {
                            detail.setDetailId(null);
                            detail.setDirectId(insuranceRisksDO.getRiskId());
                            detail.setCreateUser(user.getNameAndCode());
                            detail.setUpdateUser(user.getNameAndCode());
                        });
                        cgnciDirectInsuranceDetailService.saveBatch(detailsDOS);
                    }
                });
            }
        }

        // 分入信息
        CgnciReinsuranceInfoProjectVO divideInVO = projectVO.getDivideInVO();
        if (VerifyUtils.isNotEmpty(divideInVO)) {
            CgnciReinsuranceInfoDO divideInDO = ConvertUtils.convert(divideInVO, CgnciReinsuranceInfoDO.class);
            divideInDO.setReinsuranceId(null);
            divideInDO.setBusinessId(businessProject.getProjectId());
            divideInDO.setCreateUser(user.getNameAndCode());
            divideInDO.setUpdateUser(user.getNameAndCode());
            cgnciReinsuranceInfoService.save(divideInDO);

            List<CgnciReinsuranceRiskProjectVO> divideInRiskVOList = divideInVO.getRisks();
            if (VerifyUtils.isNotEmpty(divideInRiskVOList)) {
                divideInRiskVOList.forEach(risk -> {
                    CgnciReinsuranceRiskDO riskDO = ConvertUtils.convert(risk, CgnciReinsuranceRiskDO.class);
                    riskDO.setReinsuranceRiskId(null);
                    riskDO.setReinsuranceId(divideInDO.getReinsuranceId());
                    riskDO.setCreateUser(user.getNameAndCode());
                    riskDO.setUpdateUser(user.getNameAndCode());
                    cgnciReinsuranceRiskService.save(riskDO);

                    List<CgnciReinsuranceRiskInsuredProjectVO> riskInsureds = risk.getRiskInsureds();
                    if (VerifyUtils.isNotEmpty(riskInsureds)) {
                        riskInsureds.forEach(riskInsured -> {
                            CgnciReinsuranceRiskInsuredDO riskInsuredDO = ConvertUtils.convert(riskInsured, CgnciReinsuranceRiskInsuredDO.class);
                            riskInsuredDO.setRiskInsuredId(null);
                            riskInsuredDO.setReinsuranceRiskId(riskDO.getReinsuranceRiskId());
                            riskInsuredDO.setCreateUser(user.getNameAndCode());
                            riskInsuredDO.setUpdateUser(user.getNameAndCode());
                            cgnciReinsuranceRiskInsuredService.save(riskInsuredDO);

                            List<CgnciReinsuranceRiskLayerProjectVO> riskLayersVO = riskInsured.getRiskLayers();
                            if (VerifyUtils.isNotEmpty(riskLayersVO)) {
                                List<CgnciReinsuranceRiskLayerDO> riskLayersDO = ConvertUtils.convert(riskLayersVO, CgnciReinsuranceRiskLayerDO.class);
                                riskLayersDO.forEach(riskLayer -> {
                                    riskLayer.setLayerId(null);
                                    riskLayer.setReinsuranceRiskId(riskInsuredDO.getRiskInsuredId());
                                    riskLayer.setCreateUser(user.getNameAndCode());
                                    riskLayer.setUpdateUser(user.getNameAndCode());
                                });
                                cgnciReinsuranceRiskLayerService.saveBatch(riskLayersDO);
                            }
                        });
                    }
                });
            }
        }

        // 超净自留处理方式
        List<CgnciUnderwritingPolicyVO> underwritingPolicyVOList = projectVO.getUnderwritingPolicyVO();
        List<CgnciUnderwritingPolicyDO> underwritingPolicyDOList = ConvertUtils.convert(underwritingPolicyVOList, CgnciUnderwritingPolicyDO.class);
        underwritingPolicyDOList.forEach(policy -> {
            policy.setPolicyId(null);
            policy.setBusinessId(businessProject.getProjectId());
            policy.setCreateUser(user.getNameAndCode());
            policy.setUpdateUser(user.getNameAndCode());
        });
        cgnciUnderwritingPolicyService.saveBatch(underwritingPolicyDOList);

        // 合约分出信息
        List<CgnciReinsuranceInfoProjectVO> hyDivideOutVOList = projectVO.getHyDivideOutVOList();
        if (VerifyUtils.isNotEmpty(hyDivideOutVOList)) {
            hyDivideOutVOList.forEach(hyDivideOutVO -> {
                CgnciReinsuranceInfoDO hyDivideOutDO = ConvertUtils.convert(hyDivideOutVO, CgnciReinsuranceInfoDO.class);
                hyDivideOutDO.setReinsuranceId(null);
                hyDivideOutDO.setBusinessId(businessProject.getProjectId());
                hyDivideOutDO.setCreateUser(user.getNameAndCode());
                hyDivideOutDO.setUpdateUser(user.getNameAndCode());
                cgnciReinsuranceInfoService.save(hyDivideOutDO);

                List<CgnciReinsuranceRiskProjectVO> hyDivideOutRiskVOList = hyDivideOutVO.getRisks();
                if (VerifyUtils.isNotEmpty(hyDivideOutRiskVOList)) {
                    hyDivideOutRiskVOList.forEach(risk -> {
                        CgnciReinsuranceRiskDO riskDO = ConvertUtils.convert(risk, CgnciReinsuranceRiskDO.class);
                        riskDO.setReinsuranceRiskId(null);
                        riskDO.setReinsuranceId(hyDivideOutDO.getReinsuranceId());
                        riskDO.setCreateUser(user.getNameAndCode());
                        riskDO.setUpdateUser(user.getNameAndCode());
                        cgnciReinsuranceRiskService.save(riskDO);

                        List<CgnciReinsuranceRiskInsuredProjectVO> riskInsureds = risk.getRiskInsureds();
                        if (VerifyUtils.isNotEmpty(riskInsureds)) {
                            riskInsureds.forEach(riskInsured -> {
                                CgnciReinsuranceRiskInsuredDO riskInsuredDO = ConvertUtils.convert(riskInsured, CgnciReinsuranceRiskInsuredDO.class);
                                riskInsuredDO.setRiskInsuredId(null);
                                riskInsuredDO.setReinsuranceRiskId(riskDO.getReinsuranceRiskId());
                                riskInsuredDO.setCreateUser(user.getNameAndCode());
                                riskInsuredDO.setUpdateUser(user.getNameAndCode());
                                cgnciReinsuranceRiskInsuredService.save(riskInsuredDO);

                                List<CgnciReinsuranceRiskLayerProjectVO> riskLayersVO = riskInsured.getRiskLayers();
                                if (VerifyUtils.isNotEmpty(riskLayersVO)) {
                                    List<CgnciReinsuranceRiskLayerDO> riskLayersDO = ConvertUtils.convert(riskLayersVO, CgnciReinsuranceRiskLayerDO.class);
                                    riskLayersDO.forEach(riskLayer -> {
                                        riskLayer.setLayerId(null);
                                        riskLayer.setReinsuranceRiskId(riskInsuredDO.getRiskInsuredId());
                                        riskLayer.setCreateUser(user.getNameAndCode());
                                        riskLayer.setUpdateUser(user.getNameAndCode());
                                    });
                                    cgnciReinsuranceRiskLayerService.saveBatch(riskLayersDO);
                                }
                            });
                        }
                    });
                }
            });
        }

        // 临分分出信息
        CgnciReinsuranceInfoProjectVO lfDivideOutVO = projectVO.getLfDivideOutVO();
        if (VerifyUtils.isNotEmpty(lfDivideOutVO)) {
            CgnciReinsuranceInfoDO lfDivideOuDO = ConvertUtils.convert(lfDivideOutVO, CgnciReinsuranceInfoDO.class);
            lfDivideOuDO.setReinsuranceId(null);
            lfDivideOuDO.setBusinessId(businessProject.getProjectId());
            lfDivideOuDO.setCreateUser(user.getNameAndCode());
            lfDivideOuDO.setUpdateUser(user.getNameAndCode());
            cgnciReinsuranceInfoService.save(lfDivideOuDO);

            List<CgnciReinsuranceRiskProjectVO> lfDivideOutRiskVOList = lfDivideOutVO.getRisks();
            if (VerifyUtils.isNotEmpty(lfDivideOutRiskVOList)) {
                lfDivideOutRiskVOList.forEach(risk -> {
                    CgnciReinsuranceRiskDO riskDO = ConvertUtils.convert(risk, CgnciReinsuranceRiskDO.class);
                    riskDO.setReinsuranceRiskId(null);
                    riskDO.setReinsuranceId(lfDivideOuDO.getReinsuranceId());
                    riskDO.setCreateUser(user.getNameAndCode());
                    riskDO.setUpdateUser(user.getNameAndCode());
                    cgnciReinsuranceRiskService.save(riskDO);

                    List<CgnciReinsuranceRiskInsuredProjectVO> riskInsureds = risk.getRiskInsureds();
                    if (VerifyUtils.isNotEmpty(riskInsureds)) {
                        riskInsureds.forEach(riskInsured -> {
                            CgnciReinsuranceRiskInsuredDO riskInsuredDO = ConvertUtils.convert(riskInsured, CgnciReinsuranceRiskInsuredDO.class);
                            riskInsuredDO.setRiskInsuredId(null);
                            riskInsuredDO.setReinsuranceRiskId(riskDO.getReinsuranceRiskId());
                            riskInsuredDO.setCreateUser(user.getNameAndCode());
                            riskInsuredDO.setUpdateUser(user.getNameAndCode());
                            cgnciReinsuranceRiskInsuredService.save(riskInsuredDO);

                            List<CgnciReinsuranceRiskLayerProjectVO> riskLayersVO = riskInsured.getRiskLayers();
                            if (VerifyUtils.isNotEmpty(riskLayersVO)) {
                                List<CgnciReinsuranceRiskLayerDO> riskLayersDO = ConvertUtils.convert(riskLayersVO, CgnciReinsuranceRiskLayerDO.class);
                                riskLayersDO.forEach(riskLayer -> {
                                    riskLayer.setLayerId(null);
                                    riskLayer.setReinsuranceRiskId(riskInsuredDO.getRiskInsuredId());
                                    riskLayer.setCreateUser(user.getNameAndCode());
                                    riskLayer.setUpdateUser(user.getNameAndCode());
                                });
                                cgnciReinsuranceRiskLayerService.saveBatch(riskLayersDO);
                            }
                        });
                    }
                });
            }
        }

        // 文件信息
        List<CgnciAccessoryVO> accessoryVOList = projectVO.getAccessoryVOList();
        if (VerifyUtils.isNotEmpty(accessoryVOList)) {
            List<CgnciAccessoryDO> accessoryList = new ArrayList<>();
            accessoryVOList.forEach(accessory -> {
                CgnciAccessoryDO accessoryDO = accessoryService.getById(accessory.getAccId());
                // 设置插入数据
                accessoryDO.setAccId(null);
                accessoryDO.setBusinessId(businessProject.getProjectId());
                accessoryDO.setCreateUser(user.getNameAndCode());
                accessoryDO.setUpdateUser(user.getNameAndCode());
                accessoryList.add(accessoryDO);
            });
            accessoryService.saveBatch(accessoryList);
        }
        return businessProject;

    }

    /**
     * 项目提交审核校验
     *
     * @param checkProject
     * @param updateDTO
     */
    private void validation(CgnciBusinessProjectDO checkProject, CgnciBusinessProjectSaveOrUpdateDTO updateDTO) {
        // 校验项目名称重复，请修改
        CgnciBusinessProjectDO checkProjectName = this.getOne(new LambdaQueryWrapper<CgnciBusinessProjectDO>()
                .eq(CgnciBusinessProjectDO::getProjectName, updateDTO.getBusinessProjectUpdateDTO().getProjectName())
                .eq(CgnciBusinessProjectDO::getIsMirror, "0")
                .notIn(CgnciBusinessProjectDO::getFormNo, checkProject.getFormNo())
                .notIn(CgnciBusinessProjectDO::getStatus, Arrays.asList("0", "2", "4", "5")));
        if (VerifyUtils.isNotEmpty(checkProjectName)) {
            saveErrorMessage(String.valueOf(checkProject.getProjectId()), "项目名称重复", BusinessScenariosTypeEnum.POLICY_OBJECT.getCode(), "项目名称不可重复");
            throw new GlobalException(ResponseCodeEnum.HTTP_REQUEST_SERVICE_ERROR, "项目名称重复，请修改");
        }

        // 校验项目止期不可早于项目起期
        if (updateDTO.getBusinessProjectUpdateDTO().getStartDate().after(updateDTO.getBusinessProjectUpdateDTO().getEndDate())) {
            saveErrorMessage(String.valueOf(checkProject.getProjectId()), "项目止期不可早于项目起期", BusinessScenariosTypeEnum.POLICY_OBJECT.getCode(), "项目止期不可早于项目起期");
            throw new GlobalException(ResponseCodeEnum.HTTP_REQUEST_SERVICE_ERROR, "项目止期不可早于项目起期");
        }

        // 必须上传查勘报告
        String isSurveyReport = updateDTO.getBusinessProjectUpdateDTO().getIsSurveyReport();
        if ("1".equals(isSurveyReport)) {
            if (VerifyUtils.isEmpty(updateDTO.getAccessoryDTOList())) {
                saveErrorMessage(String.valueOf(checkProject.getProjectId()), "必须上传查勘报告", BusinessScenariosTypeEnum.POLICY_OBJECT.getCode(), "当有无查勘报告选择为“有”时，文件清单中必须存在上传文件类型“查勘报告”的文件");
                throw new GlobalException(ResponseCodeEnum.HTTP_REQUEST_SERVICE_ERROR, "必须上传查勘报告");
            }
            // 查询文件是否有查勘资料
            List<Long> accIds = updateDTO.getAccessoryDTOList().stream().map(CgnciBusinessProjectSaveOrUpdateDTO.AccessoryDTO::getAccId).collect(Collectors.toList());
            List<CgnciAccessoryDO> accessoryList = cgnciAccessoryService.listByIds(accIds);
            CgnciAccessoryDO accessory = accessoryList.stream().filter(acc -> "surveyReport".equals(acc.getAccType())).findFirst().orElse(null);
            if (VerifyUtils.isEmpty(accessory)) {
                saveErrorMessage(String.valueOf(checkProject.getProjectId()), "必须上传查勘报告", BusinessScenariosTypeEnum.POLICY_OBJECT.getCode(), "当有无查勘报告选择为“有”时，文件清单中必须存在上传文件类型“查勘报告”的文件");
                throw new GlobalException(ResponseCodeEnum.HTTP_REQUEST_SERVICE_ERROR, "必须上传查勘报告");
            }
        }



        // 校验单一险种分人的承接限额是否超该险种年度最大净自留限额,如果超出的话，需要校验单一险种临分分出限额汇总是否低于分人的承接限额-最大净自留限额，如果低于的话。提示：{险种名称-险种代码}临分分出限额超过该险种年度最大净自留限额
        List<CgnciBusinessProjectSaveOrUpdateDTO.CgnciUnderwritingPolicyProjectUpdateDTO> underwritingPolicyList = updateDTO.getUnderwritingPolicyDTO();
        if (VerifyUtils.isEmpty(underwritingPolicyList)) {
            saveErrorMessage(String.valueOf(checkProject.getProjectId()), "超净自留处理方式不能为空", BusinessScenariosTypeEnum.POLICY_OBJECT.getCode(), "超净自留处理方式不能为空");
            throw new GlobalException(ResponseCodeEnum.HTTP_REQUEST_SERVICE_ERROR, "超净自留处理方式不能为空");
        }
        // 获取分人信息
        CgnciBusinessProjectSaveOrUpdateDTO.CgnciReinsuranceInfoProjectUpdateDTO divideInDTO = updateDTO.getDivideInDTO();
        if (VerifyUtils.isEmpty(divideInDTO)) {
            saveErrorMessage(String.valueOf(checkProject.getProjectId()), "分入信息不能为空", BusinessScenariosTypeEnum.POLICY_OBJECT.getCode(), "分入信息不能为空");
            throw new GlobalException(ResponseCodeEnum.HTTP_REQUEST_SERVICE_ERROR, "分入信息不能为空");
        }
        // 获取分人险种
        List<CgnciBusinessProjectSaveOrUpdateDTO.CgnciReinsuranceRiskProjectUpdateDTO> risks = divideInDTO.getRisks();
        risks.forEach(risk -> {
            // 获取当前险种所有标的信息
            List<CgnciBusinessProjectSaveOrUpdateDTO.CgnciReinsuranceRiskInsuredProjectUpdateDTO> riskInsureds = risk.getRiskInsureds();
            // 获取当前险种所有标的的层信息
            List<CgnciBusinessProjectSaveOrUpdateDTO.CgnciReinsuranceRiskLayerProjectUpdateDTO> riskLayers =
                    riskInsureds.stream().map(CgnciBusinessProjectSaveOrUpdateDTO.CgnciReinsuranceRiskInsuredProjectUpdateDTO::getRiskLayers).flatMap(List::stream).collect(Collectors.toList());

            // 获取分入信息该险种的承接限额汇总
            BigDecimal shareLimit = BeanUtils.sumBigDecimalProperty(riskLayers, CgnciBusinessProjectSaveOrUpdateDTO.CgnciReinsuranceRiskLayerProjectUpdateDTO::getShareLimit);

            // 获取该险种超净自留处理方式
            CgnciBusinessProjectSaveOrUpdateDTO.CgnciUnderwritingPolicyProjectUpdateDTO underwritingPolicy =
                    underwritingPolicyList.stream().filter(value -> risk.getRiskSubTypeCode().equals(value.getRiskSubTypeCode())).findFirst().orElse(null);
            if (VerifyUtils.isEmpty(underwritingPolicy)) {
                saveErrorMessage(String.valueOf(checkProject.getProjectId()), "年度最大净自留限额险种-" + risk.getRiskSubType() + "为空", BusinessScenariosTypeEnum.POLICY_OBJECT.getCode(), "年度最大净自留限额险种不能为空");
                throw new GlobalException(ResponseCodeEnum.HTTP_REQUEST_SERVICE_ERROR, "年度最大净自留限额险种-" + risk.getRiskSubType() + "为空");
            }
            if (VerifyUtils.isEmpty(underwritingPolicy.getRetentionRate())) {
                throw new GlobalException(ResponseCodeEnum.HTTP_REQUEST_SERVICE_ERROR, "请配置超净自留处理方式的汇率");
            }

            BigDecimal insuredAmount = "USD".equals(underwritingPolicy.getRetentionCurrency()) ? underwritingPolicy.getInsuredAmountDollar() : underwritingPolicy.getInsuredAmountRmb();
            insuredAmount = insuredAmount.multiply(underwritingPolicy.getRetentionRate());
            // 如果分人险种的承接限额大于年度该险种年度最大净自留限额
            if (shareLimit.compareTo(insuredAmount) > 0) {
                // 获取临分分出信息，如果为空，提示错误
                CgnciBusinessProjectSaveOrUpdateDTO.CgnciReinsuranceInfoProjectUpdateDTO lfDivideOutDTO = updateDTO.getLfDivideOutDTO();
                if (VerifyUtils.isEmpty(lfDivideOutDTO)) {
                    saveErrorMessage(String.valueOf(checkProject.getProjectId()), "{" + risk.getRiskSubType() + "-" + risk.getRiskSubTypeCode() + "}承接限额超过该险种超净自留处理方式的最大净自留限额，需要为该险种设置临分分出限额", BusinessScenariosTypeEnum.POLICY_OBJECT.getCode(), "单一险种承接限额超出最大净自留限额，需要为该险种设置临分分出限额");
                    throw new GlobalException(ResponseCodeEnum.HTTP_REQUEST_SERVICE_ERROR, "{" + risk.getRiskSubType() + "-" + risk.getRiskSubTypeCode() + "}承接限额超过该险种超净自留处理方式的最大净自留限额，需要为该险种设置临分分出限额");
                }

                // 获取临分分出
                List<CgnciBusinessProjectSaveOrUpdateDTO.CgnciReinsuranceRiskProjectUpdateDTO> lfRisks = lfDivideOutDTO.getRisks();
                if (VerifyUtils.isEmpty(lfRisks)) {
                    saveErrorMessage(String.valueOf(checkProject.getProjectId()), "{" + risk.getRiskSubType() + "-" + risk.getRiskSubTypeCode() + "}承接限额超过该险种超净自留处理方式的最大净自留限额，需要为该险种设置临分分出限额", BusinessScenariosTypeEnum.POLICY_OBJECT.getCode(), "单一险种承接限额超出最大净自留限额，需要为该险种设置临分分出限额");
                    throw new GlobalException(ResponseCodeEnum.HTTP_REQUEST_SERVICE_ERROR, "{" + risk.getRiskSubType() + "-" + risk.getRiskSubTypeCode() + "}承接限额超过该险种超净自留处理方式的最大净自留限额，需要为该险种设置临分分出限额");
                }

                // 获取该险种的临分分出
                CgnciBusinessProjectSaveOrUpdateDTO.CgnciReinsuranceRiskProjectUpdateDTO lfRisk = lfRisks.stream().filter(value -> risk.getRiskSubTypeCode().equals(value.getRiskSubTypeCode())).findFirst().orElse(null);
                if (VerifyUtils.isEmpty(lfRisk)) {
                    saveErrorMessage(String.valueOf(checkProject.getProjectId()), "{" + risk.getRiskSubType() + "-" + risk.getRiskSubTypeCode() + "}承接限额超过该险种超净自留处理方式的最大净自留限额，需要为该险种设置临分分出限额", BusinessScenariosTypeEnum.POLICY_OBJECT.getCode(), "单一险种承接限额超出最大净自留限额，需要为该险种设置临分分出限额");
                    throw new GlobalException(ResponseCodeEnum.HTTP_REQUEST_SERVICE_ERROR, "{" + risk.getRiskSubType() + "-" + risk.getRiskSubTypeCode() + "}承接限额超过该险种超净自留处理方式的最大净自留限额，需要为该险种设置临分分出限额");
                }

                // 获取该险种的临分分出的分出限额汇总
                List<CgnciBusinessProjectSaveOrUpdateDTO.CgnciReinsuranceRiskInsuredProjectUpdateDTO> lfRiskInsureds = lfRisk.getRiskInsureds();
                if (VerifyUtils.isEmpty(lfRiskInsureds)) {
                    saveErrorMessage(String.valueOf(checkProject.getProjectId()), "{" + risk.getRiskSubType() + "-" + risk.getRiskSubTypeCode() + "}承接限额超过该险种超净自留处理方式的最大净自留限额，需要为该险种设置临分分出限额", BusinessScenariosTypeEnum.POLICY_OBJECT.getCode(), "单一险种承接限额超出最大净自留限额，需要为该险种设置临分分出限额");
                    throw new GlobalException(ResponseCodeEnum.HTTP_REQUEST_SERVICE_ERROR, "{" + risk.getRiskSubType() + "-" + risk.getRiskSubTypeCode() + "}承接限额超过该险种超净自留处理方式的最大净自留限额，需要为该险种设置临分分出限额");
                }

                List<CgnciBusinessProjectSaveOrUpdateDTO.CgnciReinsuranceRiskLayerProjectUpdateDTO> lfRiskLayers =
                        lfRiskInsureds.stream().map(CgnciBusinessProjectSaveOrUpdateDTO.CgnciReinsuranceRiskInsuredProjectUpdateDTO::getRiskLayers).flatMap(List::stream).collect(Collectors.toList());
                BigDecimal cededLimit = BeanUtils.sumBigDecimalProperty(lfRiskLayers, CgnciBusinessProjectSaveOrUpdateDTO.CgnciReinsuranceRiskLayerProjectUpdateDTO::getCededLimit);
                // 如果该险种的临分分出的分出限额汇总低于分人的承接限额-最大净自留限额，提示错误
                if (cededLimit.compareTo(shareLimit.subtract(insuredAmount)) < 0) {
                    saveErrorMessage(String.valueOf(checkProject.getProjectId()), "{" + risk.getRiskSubType() + "-" + risk.getRiskSubTypeCode() + "}分出后的分出限额超过该险种超净自留处理方式的最大净自留限额", BusinessScenariosTypeEnum.POLICY_OBJECT.getCode(), "单一险种分出后的分出限额超过该险种超净自留处理方式的最大净自留限额\n" +
                            "注：仅考虑临分分出后自留额，合约分出暂不考虑");
                    throw new GlobalException(ResponseCodeEnum.HTTP_REQUEST_SERVICE_ERROR, "{" + risk.getRiskSubType() + "-" + risk.getRiskSubTypeCode() + "}分出后的分出限额超过该险种超净自留处理方式的最大净自留限额");
                }
            }
        });


     /*   // 校验单一险种分出后的自留额是否超该险种年度的最大净自留限额(仅考虑临分分出后自留额，合约分出暂不考虑) 提示：{险种名称-险种代码}分出后的自留额超过该险种年度最大净自留限额
        CgnciBusinessProjectSaveOrUpdateDTO.CgnciReinsuranceInfoProjectUpdateDTO lfDivideOutDTO = updateDTO.getLfDivideOutDTO();
        if (VerifyUtils.isNotEmpty(lfDivideOutDTO)) {
            //String reinsuranceMethod = lfDivideOutDTO.getReinsuranceMethod();
            List<CgnciBusinessProjectSaveOrUpdateDTO.CgnciReinsuranceRiskProjectUpdateDTO> lfRisks = lfDivideOutDTO.getRisks();
            lfRisks.forEach(risk -> {
                // 查询文件是否有董事会最大净自留审核文件,如果有的话,不需要校验分出后的自留额是否超该险种年度最大净自留限额
                *//*List<CgnciBusinessProjectSaveOrUpdateDTO.AccessoryDTO> accessoryDTOList = updateDTO.getAccessoryDTOList();
                if (VerifyUtils.isNotEmpty(accessoryDTOList)) {
                    List<Long> accIds = accessoryDTOList.stream().map(CgnciBusinessProjectSaveOrUpdateDTO.AccessoryDTO::getAccId).collect(Collectors.toList());
                    List<CgnciAccessoryDO> accessoryList = cgnciAccessoryService.listByIds(accIds);
                    CgnciAccessoryDO accessory = accessoryList.stream().filter(acc -> "boardRetentionDoc".equals(acc.getAccType())).findFirst().orElse(null);
                    if (VerifyUtils.isNotEmpty(accessory)) {
                        return;
                    }
                }*//*

                // 获取该险种超净自留处理方式
                CgnciBusinessProjectSaveOrUpdateDTO.CgnciUnderwritingPolicyProjectUpdateDTO underwritingPolicy =
                        underwritingPolicyList.stream().filter(value -> risk.getRiskSubTypeCode().equals(value.getRiskSubTypeCode())).findFirst().orElse(null);
                if (VerifyUtils.isEmpty(underwritingPolicy)) {
                    saveErrorMessage(String.valueOf(checkProject.getProjectId()), "年度最大净自留限额险种-" + risk.getRiskSubType() + "为空", BusinessScenariosTypeEnum.POLICY_OBJECT.getCode(), "年度最大净自留限额险种不能为空");
                    throw new GlobalException(ResponseCodeEnum.HTTP_REQUEST_SERVICE_ERROR, "年度最大净自留限额险种-" + risk.getRiskSubType() + "为空");
                }
                *//*if (VerifyUtils.isEmpty(underwritingPolicy.getRetentionRate())) {
                    throw new GlobalException(ResponseCodeEnum.HTTP_REQUEST_SERVICE_ERROR, "请配置超净自留处理方式的汇率");
                }
                BigDecimal insuredAmount = "USD".equals(underwritingPolicy.getRetentionCurrency()) ? underwritingPolicy.getInsuredAmountDollar() : underwritingPolicy.getInsuredAmountRmb();
                insuredAmount = insuredAmount.multiply(underwritingPolicy.getRetentionRate());*//*
                BigDecimal totalRetentionAmount = underwritingPolicy.getRetentionAmount();

                // 获取当前险种所有标的的险种层信息
                List<CgnciBusinessProjectSaveOrUpdateDTO.CgnciReinsuranceRiskInsuredProjectUpdateDTO> riskInsureds = risk.getRiskInsureds();
                List<CgnciBusinessProjectSaveOrUpdateDTO.CgnciReinsuranceRiskLayerProjectUpdateDTO> riskLayers =
                        riskInsureds.stream().map(CgnciBusinessProjectSaveOrUpdateDTO.CgnciReinsuranceRiskInsuredProjectUpdateDTO::getRiskLayers).flatMap(List::stream).collect(Collectors.toList());
                BigDecimal engagedLimit = BeanUtils.sumBigDecimalProperty(riskLayers, CgnciBusinessProjectSaveOrUpdateDTO.CgnciReinsuranceRiskLayerProjectUpdateDTO::getEngagedLimit);
                BigDecimal cededLimit = BeanUtils.sumBigDecimalProperty(riskLayers, CgnciBusinessProjectSaveOrUpdateDTO.CgnciReinsuranceRiskLayerProjectUpdateDTO::getCededLimit);
                BigDecimal retentionAmount = engagedLimit.subtract(cededLimit);
                if (retentionAmount.compareTo(totalRetentionAmount) > 0) {
                    saveErrorMessage(String.valueOf(checkProject.getProjectId()), "{" + risk.getRiskSubType() + "-" + risk.getRiskSubTypeCode() + "}分出后的自留额超过该险种超净自留处理方式的自留额", BusinessScenariosTypeEnum.POLICY_OBJECT.getCode(), "单一险种分出后的自留额是否超该险种年度自留额\n" +
                            "注：仅考虑临分分出后自留额，合约分出暂不考虑");
                    throw new GlobalException(ResponseCodeEnum.HTTP_REQUEST_SERVICE_ERROR, "{" + risk.getRiskSubType() + "-" + risk.getRiskSubTypeCode() + "}分出后的自留额超过该险种超净自留处理方式的自留额");
                }


              *//*  switch (reinsuranceMethod) {
                    case "1":
                        // 比例的时候，获取临分分出信息该险种的自留额
                        retentionAmount = BeanUtils.sumBigDecimalProperty(riskLayers, CgnciBusinessProjectSaveOrUpdateDTO.CgnciReinsuranceRiskLayerProjectUpdateDTO::getRetentionAmount);
                        if (retentionAmount.compareTo(insuredAmount) > 0) {
                            saveErrorMessage(String.valueOf(checkProject.getProjectId()), "{" + risk.getRiskSubType() + "-" + risk.getRiskSubTypeCode() + "}分出后的自留额超过该险种年度最大净自留限额,必须上传董事会最大净自留审核文件", BusinessScenariosTypeEnum.POLICY_OBJECT.getCode(), "单一险种分出后的自留额是否超该险种年度最大净自留限额\n" +
                                    "注：仅考虑临分分出后自留额，合约分出暂不考虑");
                            throw new GlobalException(ResponseCodeEnum.HTTP_REQUEST_SERVICE_ERROR, "{" + risk.getRiskSubType() + "-" + risk.getRiskSubTypeCode() + "}分出后的自留额超过该险种年度最大净自留限额,必须上传董事会最大净自留审核文件");
                        }
                        break;
                    case "2":
                        // 非比例的时候，获取临分分出信息该险种的自留额(自留额=分入限额-分出限额)
                        BigDecimal engagedLimit = BeanUtils.sumBigDecimalProperty(riskLayers, CgnciBusinessProjectSaveOrUpdateDTO.CgnciReinsuranceRiskLayerProjectUpdateDTO::getEngagedLimit);
                        BigDecimal cededLimit = BeanUtils.sumBigDecimalProperty(riskLayers, CgnciBusinessProjectSaveOrUpdateDTO.CgnciReinsuranceRiskLayerProjectUpdateDTO::getCededLimit);
                        retentionAmount = engagedLimit.subtract(cededLimit);
                        if (retentionAmount.compareTo(insuredAmount) > 0) {
                            saveErrorMessage(String.valueOf(checkProject.getProjectId()), "{" + risk.getRiskSubType() + "-" + risk.getRiskSubTypeCode() + "}分出后的自留额超过该险种年度最大净自留限额,必须上传董事会最大净自留审核文件", BusinessScenariosTypeEnum.POLICY_OBJECT.getCode(), "单一险种分出后的自留额是否超该险种年度最大净自留限额\n" +
                                    "注：仅考虑临分分出后自留额，合约分出暂不考虑");
                            throw new GlobalException(ResponseCodeEnum.HTTP_REQUEST_SERVICE_ERROR, "{" + risk.getRiskSubType() + "-" + risk.getRiskSubTypeCode() + "}分出后的自留额超过该险种年度最大净自留限额,必须上传董事会最大净自留审核文件");
                        }
                        break;
                    default:
                        throw new GlobalException(ResponseCodeEnum.HTTP_REQUEST_SERVICE_ERROR);
                }*//*
            });
        }*/

        // 校验该业务倒签，请上传倒签资料
        /*if (checkProject.getCreateTime().after(DateUtils.getTimeByType(updateDTO.getBusinessProjectUpdateDTO().getStartDate(), "start"))) {
            if (VerifyUtils.isEmpty(updateDTO.getAccessoryDTOList())) {
                saveErrorMessage(String.valueOf(checkProject.getProjectId()), "该业务倒签，请上传倒签资料", BusinessScenariosTypeEnum.POLICY_OBJECT.getCode(), "项目倒签，在流转至总经理前未上传倒签资料");
                throw new GlobalException(ResponseCodeEnum.HTTP_REQUEST_SERVICE_ERROR, "该业务倒签，请上传倒签资料");
            }
            // 查询文件是否有倒签资料
            List<Long> accIds = updateDTO.getAccessoryDTOList().stream().map(CgnciBusinessProjectSaveOrUpdateDTO.AccessoryDTO::getAccId).collect(Collectors.toList());
            List<CgnciAccessoryDO> accessoryList = cgnciAccessoryService.listByIds(accIds);
            CgnciAccessoryDO accessory = accessoryList.stream().filter(acc -> "backInformation".equals(acc.getAccType())).findFirst().orElse(null);
            if (VerifyUtils.isEmpty(accessory)) {
                saveErrorMessage(String.valueOf(checkProject.getProjectId()), "该业务倒签，请上传倒签资料", BusinessScenariosTypeEnum.POLICY_OBJECT.getCode(), "项目倒签，在流转至总经理前未上传倒签资料");
                throw new GlobalException(ResponseCodeEnum.HTTP_REQUEST_SERVICE_ERROR, "该业务倒签，请上传倒签资料");
            }
        }*/

        // 校验项目起保日期不在合约生效期间内
        List<CgnciBusinessProjectSaveOrUpdateDTO.CgnciReinsuranceInfoProjectUpdateDTO> hyDivideOutDTOList = updateDTO.getHyDivideOutDTOList();
        if (VerifyUtils.isNotEmpty(hyDivideOutDTOList)) {
            // 查询合约的起止日期
            CgnciBusinessInsuranceDO hyInsurance = businessInsuranceService.getOne(new LambdaQueryWrapper<CgnciBusinessInsuranceDO>().eq(CgnciBusinessInsuranceDO::getBusinessNo, hyDivideOutDTOList.get(0).getContractNo()).eq(CgnciBusinessInsuranceDO::getIsMirror, "0").eq(CgnciBusinessInsuranceDO::getStatus, "3"));
            if (updateDTO.getBusinessProjectUpdateDTO().getStartDate().before(hyInsurance.getStartDate()) || updateDTO.getBusinessProjectUpdateDTO().getStartDate().after(hyInsurance.getEndDate())) {
                saveErrorMessage(String.valueOf(checkProject.getProjectId()), "项目起保日期不在合约生效期间内", BusinessScenariosTypeEnum.POLICY_OBJECT.getCode(), "项目起保日期需在合约生效期间内");
                throw new GlobalException(ResponseCodeEnum.HTTP_REQUEST_SERVICE_ERROR, "项目起保日期不在合约生效期间内");
            }

            // {险种XX}不在合约的险种范围内
            List<CgnciBusinessProjectSaveOrUpdateDTO.CgnciUnderwritingPolicyProjectUpdateDTO> underwritingPolicyDTO = updateDTO.getUnderwritingPolicyDTO();
            // 过滤掉分出安排是合约分出的list
            underwritingPolicyDTO = underwritingPolicyDTO.stream().filter(value -> value.getReinsuranceArrangement().contains("2")).collect(Collectors.toList());
            String[] riskSubTypes = underwritingPolicyDTO.stream()
                    .map(CgnciBusinessProjectSaveOrUpdateDTO.CgnciUnderwritingPolicyProjectUpdateDTO::getRiskSubType)
                    .collect(Collectors.joining(",")).split(",");

            for (String riskSubType : riskSubTypes) {
                AtomicBoolean flag = new AtomicBoolean(false);
                Map<String, List<CgnciBusinessProjectSaveOrUpdateDTO.CgnciReinsuranceInfoProjectUpdateDTO>> hyDivideOutMap = hyDivideOutDTOList.stream().collect(Collectors.groupingBy(CgnciBusinessProjectSaveOrUpdateDTO.CgnciReinsuranceInfoProjectUpdateDTO::getContractNo));
                hyDivideOutMap.forEach((contractNo, hyDivideOutList) -> {
                    for (CgnciBusinessProjectSaveOrUpdateDTO.CgnciReinsuranceInfoProjectUpdateDTO hyDivideOut : hyDivideOutList) {
                        List<CgnciBusinessProjectSaveOrUpdateDTO.CgnciReinsuranceRiskProjectUpdateDTO> hyRisks = hyDivideOut.getRisks();
                        CgnciBusinessProjectSaveOrUpdateDTO.CgnciReinsuranceRiskProjectUpdateDTO cgnciReinsuranceRiskProjectUpdateDTO = hyRisks.stream().filter(value -> riskSubType.trim().equals(value.getRiskSubType().trim())).findFirst().orElse(null);
                        if (VerifyUtils.isNotEmpty(cgnciReinsuranceRiskProjectUpdateDTO)) {
                            flag.set(true);
                            break;
                        }
                    }
                });
                if (!flag.get()) {
                    saveErrorMessage(String.valueOf(checkProject.getProjectId()), "{险种-" + riskSubType + "}不在合约的险种范围内", BusinessScenariosTypeEnum.POLICY_OBJECT.getCode(), "需要合约分出的险种不在合约的险种范围内");
                    throw new GlobalException(ResponseCodeEnum.HTTP_REQUEST_SERVICE_ERROR, "{险种-" + riskSubType + "}不在合约的险种范围内");
                }
            }
        }
    }

    @Autowired
    private CgnciClaimAlertInfoService cgnciClaimAlertInfoService;

    private void saveErrorMessage(String taskNo, String content, String businessSceneType, String ruleName) {
        CgnciClaimAlertInfoDO info = new CgnciClaimAlertInfoDO();
        info.setContent(content);
        info.setRuleName(ruleName);
        info.setBusinessNo(taskNo);
        info.setAlertType(AlertInfoTypeEnum.ERROR.getCode());
        info.setBusinessScene(BusinessScenariosEnum.POLICY.getCode());
        info.setBusinessSceneType(businessSceneType);
        cgnciClaimAlertInfoService.clearHistoryAndSave(info);
    }

}
